﻿using cszmcaux;
using LKL_Code.MotionControlCard;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using static LKL_Code.MotionControlCard.IInterpolation;


namespace LKLCode.MotionControlCard.Zmotion
{
    /// <summary>
    /// 正运动插补对象
    /// </summary>
    public class ZmcInterpolation : IInterpolation
    {
        private IntPtr zmc_Hanle;//控制卡句柄
        private int[] axisList;  //插补的轴列表

        /// <summary>
        /// 插补对象与初始化
        /// </summary>
        /// <param name="zmc_Hanle"></param>
        /// <param name="axisList"></param>
        public ZmcInterpolation(IntPtr zmc_Hanle, int[] axisList)
        {
            this.zmc_Hanle = zmc_Hanle;
            this.axisList = axisList;
            this.EnableMerge = false;
        }

        /// <summary>
        /// 暂停方式
        /// </summary>
        public int PauseType
        {
            //暂停方式：
            //0暂停当前运动。
            //1在当前运动完成后正准备执行下一条运动指令时暂停。
            //2 在当前运动完成后正准备执行下一条运动指令时，并且两条指令
            //的 MARK 标识不一样时暂停。这个模式可以用于一个动作由多个指
            //令来实现时，可以在一整个动作完成后暂停。
            get { return _pauseType; }
            set { _pauseType = value; }
        }
        private int _pauseType;

        /// <summary>
        /// 插补运动状态 0-没有完成 -- 1-运动完成
        /// </summary>
        public AxisMoveStatus MoveStatus
        {
            get
            {
                try
                {
                    int status = 1;
                    //返回状态 0-没有完成  -- 1-运动完成
                    zmcaux.ZAux_Direct_GetIfIdle(zmc_Hanle, axisList[0], ref status);

                    if (status == 0)
                    {
                        return AxisMoveStatus.Moving;
                    }
                    else
                    {
                        return AxisMoveStatus.Finish;
                    }
                }
                catch
                {
                    return AxisMoveStatus.GetIndoErr;
                }
            }
            

        }

        /// <summary>
        /// 插补状态
        /// </summary>
        public Interpolation_Status Status { get { return status; } }
        private Interpolation_Status status;

        /// <summary>
        /// 插补速度
        /// </summary>
        public float Speed
        {
            get
            {
                float val = 0;
                zmcaux.ZAux_Direct_GetSpeed(zmc_Hanle, axisList[0], ref val);
                return val;
            }
            set
            {
                zmcaux.ZAux_Direct_SetSpeed(zmc_Hanle, axisList[0], value);
            }
        }


        /// <summary>
        /// 插补加速度
        /// </summary>
        public float Accel
        {
            get
            {
                float val = 0;
                zmcaux.ZAux_Direct_GetAccel(zmc_Hanle, axisList[0], ref val);
                return val;
            }
            set
            {
                zmcaux.ZAux_Direct_SetAccel(zmc_Hanle, axisList[0], value);
            }
        }

        /// <summary>
        /// 插补减速度
        /// </summary>
        public float Decel
        {
            get
            {
                float val = 0;
                zmcaux.ZAux_Direct_GetDecel(zmc_Hanle, axisList[0], ref val);
                return val; ;
            }
            set
            {
                zmcaux.ZAux_Direct_SetDecel(zmc_Hanle, axisList[0], value);
            }
        }

        /// <summary>
        /// 连续插补开关
        /// </summary>
        public bool EnableMerge
        {
            get
            {
                int val = 0;
                zmcaux.ZAux_Direct_GetMerge(zmc_Hanle, axisList[0], ref val);
                return val == 1 ? true : false;
            }
            set
            {
                zmcaux.ZAux_Direct_SetMerge(zmc_Hanle, axisList[0], value == true ? 1 : 0);
            }
        }

        /// <summary>
        /// 执行直线插补
        /// </summary>
        /// <param name="distanceList"></param>
        public void MoveAbs(List<double[]> distancesList)
        {
            int iresult;//结果

            for (int i = 0; i < distancesList.Count; i++)
            {
                //是否暂停
                PauseSleep();

                //是否急停跳出
                if (status.IsEmergentStop) return;

                /*
                //将一个列表中的元素转换为浮点数组
                //.ToList(): 将distancesList[i]转换为一个List对象。
                //.ConvertAll(x => (float)(x)): 使用ConvertAll方法将列表中的每个元素转换为float类型。
                //x => (float)(x)是一个lambda表达式，用于定义转换规则。
                //.ToArray(): 将转换后的List<float>转换为float[]数组。
                */
                float[] distances = distancesList[i].ToList().ConvertAll(x => (float)x).ToArray();

                iresult = zmcaux.ZAux_Direct_MoveAbs(zmc_Hanle, axisList.Length, axisList, distances); //2轴插补指令,函数返回非0 则表示发送不成功，缓冲区可能满了，重新发送

                while(iresult != 0)
                {
                    if (status.IsEmergentStop) return;//急停跳出
                    PauseSleep();//暂停卡住
                    iresult = zmcaux.ZAux_Direct_MoveAbs(zmc_Hanle, axisList.Length, axisList, distances);
                    Thread.Sleep(1);//1毫秒
                }
            }
        }

        /// <summary>
        /// 等待完成插补
        /// </summary>
        public void WaitMoveAbsOver()
        {
            if(status.IsEmergentStop == true) return;

            while(MoveStatus!=  AxisMoveStatus.Finish) 
            {
                if (status.IsEmergentStop == true) break;
                Thread.Sleep(1);
            }
        }



        /// <summary>
        /// 急停
        /// </summary>
        public void EmergentStop()
        {
            status.IsEmergentStop = true;
            for(int i = 0; i < axisList.Length; i++) 
            {
                zmcaux.ZAux_Direct_Single_Cancel(zmc_Hanle, axisList[i], 3);
            }
        }

        public void ResetEmergentStop()
        {
            status.IsPause = false;
            status.IsEmergentStop = false;
        }

     
        public void Pause()
        {
            status.IsPause = true;
            zmcaux.ZAux_Direct_MovePause(zmc_Hanle, axisList[0], _pauseType);
        }

        public void Resume()
        {
            status.IsPause = false;
            zmcaux.ZAux_Direct_MoveResume(zmc_Hanle, axisList[0]);
        }
        


        /// <summary>
        /// 插补暂停线程阻塞
        /// </summary>
        public void PauseSleep()
        {
            while (status.IsPause)
            {
                if (status.IsEmergentStop == true) return;
                Thread.Sleep(1);
            }
        }


































    }
}
